package simulator.srcv2;

import simulator.srcv2.TxRxEvent.TxRxEventType;

public class TxRxSystem {

    // Parametros da simulação
	final static int MAX_DATA  = 3000;
	
	final static int DATA_SIZE = 400*8;
	final static double INTERVAL = 0.250;
	
	final static double RITMO_BINARIO = 10000.0;
	//final static double DISTANCIA     = 5000000.0;
	final static double DISTANCIA     = 0.0;
	
	// Contadores Estatisticos	
    static double delayQ   = 0.0;
	static double delayQtx = 0.0;
	static double delaySys = 0.0;
	
	public static void main(String[] args) {
		Simulator.setLogLevel(Simulator.LogLevel.FULLDEBUG);	

		//Simulator.setDataFile("/home/rdi/Desktop/data.txt");
		//Simulator.setDataFile("C:/Users/Stephane/Desktop/data.txt");
		String s="#Simulation Results \n";
		s=s+"#Ntramas \t"+MAX_DATA+"\n";
		s=s+"#L \t\t"+DATA_SIZE+"\n";
		s=s+"#TaxaChegadas \t"+INTERVAL+"\n";
		s=s+"#Rb \t\t"+RITMO_BINARIO+"\n";
		s=s+"#d \t\t"+DISTANCIA+"\n";		
		Simulator.data(s);
		
		/* Variáveis de estado - participantes no sistema */
		Source     source   = new Source(MAX_DATA, DATA_SIZE, INTERVAL);
		Receiver   receiver = new Receiver();
		Transmiter transmiter    = new Transmiter(RITMO_BINARIO, DISTANCIA);
				
		/* Evento que arranca a simulação - abertura do serviço no instante 0.0 */
		TxRxEvent seed = new TxRxEvent(0.0, TxRxEventType.Generate_DATA, null);
		Simulator.addEvent(seed);

		/* Evento actual - o que se está a processar em cada ciclo */
		TxRxEvent current = (TxRxEvent)Simulator.nextEvent();

		/* Ciclo central da simulação */
		while (current!=null) {
			
			switch ((TxRxEvent.TxRxEventType)(current.type())) {
			    // Processamento de cada um dos tipos de acontecimentos
				case Generate_DATA:
					source.generateData(current);
					break;
					
				case Arrival_DATA:
					transmiter.arrivalData((Data)current.data());
					break;
					
				case StopTX:
					transmiter.stopTx((Data)current.data());
					break;
					
				case StartRX:
					receiver.startRX((Data)(current.data()));
					break;
				
				case StopRX:
					receiver.stopRX((Data)(current.data()));
					break;
					
				case ARRIVAL_ACK:
					transmiter.arrivalACK((Data)(current.data()));
					break;	
				
				case TIMEOUT:
					transmiter.timeout((Data)(current.data()));
					break;	
			}					
			/* Retira da lista o próximo acontecimento */
			current = (TxRxEvent) Simulator.nextEvent();	
		}
		Simulator.info("FIM.");
		
		// Impressão dos resultados da simulação.
		Simulator.info("STATS.");
		s = "Avg. delayQ = "+(delayQ/(double)MAX_DATA)+"\n";
		s = s+"Avg. delayQTx = "+(delayQtx/(double)MAX_DATA)+"\n";
		s = s+"Avg. delaySys = "+(delaySys/(double)MAX_DATA)+"\n";
		s = s+"Numero medio de tramas na fila, Nq = "+(delayQ/Simulator.getClock())+"\n";
		s = s+"Numero medio de tramas na fila ou a transmitir, Nqtx = "+(delayQtx/Simulator.getClock())+"\n";
		s = s+"Numero medio de tramas no sistema total, Nsistema = "+(delaySys/Simulator.getClock())+"\n";
		Simulator.info(s);
	}
		
}
